package com.zbkj.admin.listener;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.SystemClock;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.stream.SimpleCollector;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.query.QueryWrapper;
import com.zbkj.admin.boot.redisson.command.Redis;
import com.zbkj.admin.boot.redisson.locker.RedisLockClient;
import com.zbkj.admin.boot.redisson.queue.RDQListener;
import com.zbkj.admin.constants.OrderListenerConstants;
import com.zbkj.admin.constants.ProductConstants;
import com.zbkj.admin.mapper1.EbNoParticipationMapper;
import com.zbkj.admin.mapper1.EbOrderProductVoucherRecordMapper;
import com.zbkj.admin.mapper1.EbUserBalanceRecordMapper;
import com.zbkj.admin.model.order.Order;
import com.zbkj.admin.model.order.OrderDetail;
import com.zbkj.admin.model.product.Product;
import com.zbkj.admin.model.product.ProductAttrValue;
import com.zbkj.admin.model.seckill.SeckillActivity;
import com.zbkj.admin.model.seckill.SeckillProduct;
import com.zbkj.admin.model.user.User;
import com.zbkj.admin.pojo.*;
import com.zbkj.admin.service.*;
import com.zbkj.admin.front.service.FrontOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 订单创建后的
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class OrderCreateListener {


    private static final String ORDER_FREEZE = "冻结积分", ORDER_BALANCE = "冻结余额", ORDER_SEE_POINT = "见点";
    private static final Duration ORDER_TIMEOUT = Duration.ofHours(2L);
    /**
     * 自动确认收货redis key
     */
    private static final String ORDER_AUTO_CONFIRM = "order:auto_confirm", ORDER_PROMOTION = "order:promotion:";
    private static final String ORDER_PROMOTION_DETAIL = "order:promotion:detail:", ORDER_SECKILL = "order:seckill:",
            ORDER_PRODUCT = "order:product:temporary:", ORDER_VOUCHER = "order:voucher:temporary:";

    private final Redis redis;
    private final UserService userService;
    private final OrderService orderService;
    private final ProductService productService;
    //    private final EbProductMapper ebProductMapper;
    private final RedisLockClient redisLockClient;
    private final FrontOrderService frontOrderService;
    private final OrderDetailService orderDetailService;
    private final EbOrderProductVoucherRecordMapper orderVoucherRecordMapper;
    private final RedisTemplate<Object, Object> redisTemplate;
    private final SeckillProductService seckillProductService;
    private final EbUserBalanceRecordMapper balanceRecordMapper;
    private final ProductAttrValueService productAttrValueService;
    private final EbDividendConfigService ebDividendConfigService;
    private final EbUserRelationshipService userRelationshipService;
    private final SeckillActivityService seckillActivityService;
    private final EbNoParticipationMapper ebNoParticipationMapper;
    //    private IEbUserIntegralProductRecordService productRecordService;
    private final IEbUserIntegralProductRecordService integralProductRecordService;


    /**
     * 订单退款流水回退
     */
    @Transactional(rollbackFor = Exception.class)
    public void refund() {

    }


    /**
     * 订单完成佣金(抵用券记录)
     */
    @Transactional(rollbackFor = Exception.class)
    public void voucherCommission(String orderId) {
        redisLockClient.lockReentrant(ORDER_VOUCHER + orderId, 600L, 1200L, () -> {
            List<EbOrderProductVoucherRecordEntity> dataList = new ArrayList<>();
            Map<String, Object> map = new HashMap<>();

            handlerOrderData(orderId, (product, orderDetails, order, uid, isSeckill) -> {
                Integer productNum = getProductNum(orderId, product.getId());
                BigDecimal integral = isSeckill ? product.getPoints().multiply(BigDecimal.valueOf(productNum))
                        .setScale(2, RoundingMode.DOWN) : product.getPoints().multiply(BigDecimal.valueOf(productNum));
                return MapUtil.builder(map).put(String.valueOf(product.getId()), integral).build();
            });

            Order orderInfo = orderService.getByOrderNo(orderId);
            dataList.add(EbOrderProductVoucherRecordEntity.builder().uid(Long.valueOf(orderInfo.getUid()))
                    .orderNo(orderId).data(map).build());

            if (CollUtil.isNotEmpty(dataList)) {
                orderVoucherRecordMapper.insertBatch(dataList);
                map.clear();
            }
            return true;
        });
    }

    /**
     * 订单结束处理
     */
    @RDQListener(OrderListenerConstants.ORDER_COMMISSION)
    @Transactional(rollbackFor = Exception.class)
    public void commission(String orderId) {

        Order orderInfo = orderService.getByOrderNo(orderId);
        EbUserRelationshipEntity one = userRelationshipService.getOne(QueryWrapper.create().from(EbUserRelationshipEntity.class)
                .where(EbUserRelationshipEntity::getUid).eq(orderInfo.getUid()).eq(EbUserRelationshipEntity::getIsEstablish, 1));
        EbUserRelationshipEntity two = null;
        if (Objects.nonNull(one)) {
            two = userRelationshipService.getOne(QueryWrapper.create()
                    .from(EbUserRelationshipEntity.class).where(EbUserRelationshipEntity::getUid)
                    .eq(one.getPId()).eq(EbUserRelationshipEntity::getIsEstablish, 1));
        }
        List<EbUserRelationshipEntity> three = null;
        if (Objects.nonNull(two)) {
            three = userRelationshipService.list(QueryWrapper.create()
                    .from(EbUserRelationshipEntity.class).where(EbUserRelationshipEntity::getPId)
                    .eq(two.getUid()).eq(EbUserRelationshipEntity::getIsEstablish, 1));
        }

        List<Long> uid = Objects.isNull(one) ? new ArrayList<>(orderInfo.getUid()) :
                Stream.of(two).filter(Objects::nonNull).flatMap(t -> Stream.of(t.getUid(), t.getPId()))
                        .collect(Collectors.toList());
        if (Objects.isNull(two)) {
            uid.add(Long.valueOf(orderInfo.getUid()));
        }
        List<Long> ids = new ArrayList<>();
        if (Objects.nonNull(three)) {
            // 三级
            uid.addAll(three.stream().map(EbUserRelationshipEntity::getUid).toList());
        }
        uid.forEach(it -> {
            if (!it.equals(0L)) {
                ids.add(it);
            }
        });
        List<EbUserBalanceRecordEntity> ebUserBalance = new ArrayList<>();
        List<Integer> userids = new ArrayList<>(), list = new ArrayList<>();
        List<EbUserIntegralProductRecordEntity> productRecordEntities = new ArrayList<>();
        AtomicReference<List<EbUserBalanceRecordEntity>> ebUserBalanceRecordList = new AtomicReference<>();
        AtomicReference<List<EbUserIntegralProductRecordEntity>> listed = new AtomicReference<>();
        LogicDeleteManager.execWithoutLogicDelete(() -> {
            if (CollUtil.isNotEmpty(ids)) {
                ebUserBalanceRecordList.set(balanceRecordMapper.selectListByQuery(QueryWrapper.create()
                        .from(EbUserBalanceRecordEntity.class)
                        .in(EbUserBalanceRecordEntity::getUid, ids)
                        .eq(EbUserBalanceRecordEntity::getLinkId, orderId).eq(EbUserBalanceRecordEntity::getType, 3)));
                listed.set(integralProductRecordService
                        .list(integralProductRecordService.from().where(EbUserIntegralProductRecordEntity::getUid)
                                .in(ids).eq(EbUserIntegralProductRecordEntity::getLinkId, orderId)
                                .eq(EbUserIntegralProductRecordEntity::getStatus, 2)));
            }

        });
        // 余额解冻
        if (CollUtil.isNotEmpty(ebUserBalanceRecordList.get())) {
            ebUserBalanceRecordList.get().forEach(ebUserBalanceRecordEntity -> {
                String format = StrUtil.format("用户订单已完成解冻余额{}元", ebUserBalanceRecordEntity.getAmount());
                userids.add(ebUserBalanceRecordEntity.getId());
                ebUserBalanceRecordEntity.setBalance(ebUserBalanceRecordEntity.getBalance()
                                .add(ebUserBalanceRecordEntity.getAmount()))
                        .setRemark(format).setType(1);
                // 更新用户余额
                User byId = userService.getById(ebUserBalanceRecordEntity.getUid());
                byId.setNowMoney(byId.getNowMoney().add(ebUserBalanceRecordEntity.getAmount()));
                userService.updateById(byId);
                ebUserBalanceRecordEntity.setId(null);
                ebUserBalance.add(ebUserBalanceRecordEntity);
            });
        }
        // 积分解冻
/*        if (CollUtil.isNotEmpty(listed.get())) {
            listed.get().forEach(recordServiceOne -> {
                String format = StrUtil.format("用户订单已完成解冻积分{}元", recordServiceOne.getIntegral());
//                integralProductRecordService.removeById(recordServiceOne);
                list.add(recordServiceOne.getId());
                recordServiceOne.setBalance(recordServiceOne.getBalance().add(recordServiceOne.getIntegral()));
                recordServiceOne.setType(1).setStatus(3).setId(null).setMark(format);
                productRecordEntities.add(recordServiceOne);
            });
        }*/
        balanceRecordMapper.deleteBatchByIds(userids);
        balanceRecordMapper.insertBatch(ebUserBalance);
        integralProductRecordService.saveBatch(productRecordEntities);
        integralProductRecordService.removeByIds(list);
        // 删除自动确认订单
        redisTemplate.opsForZSet().remove(ORDER_AUTO_CONFIRM, orderId);
    }

    /**
     * 订单冻结余额
     */
    @RDQListener(OrderListenerConstants.ORDER_USER_BALANCE)
    @Transactional(rollbackFor = Exception.class)
    @SuppressWarnings("all")
    public void userBalance(String orderId) {
        var dividendConfig = ebDividendConfigService.getOne(ebDividendConfigService.from().orderBy(EbDividendConfigEntity::getCreatedTime).desc().limit(1));
        Order orderInfo = orderService.getByOrderNo(orderId);
        List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(orderId);
        // 秒杀商品
        List<OrderDetail> orderDetailInfo = orderDetailList.stream().parallel()
                .filter(orderDetail -> orderDetail.getProductMarketingType() == 1).toList();
        if (!orderDetailInfo.isEmpty()) {
            // 新人福利退出
            Integer productId = orderDetailInfo.getFirst().getProductId();
            if (Objects.nonNull(productId)) {
                SeckillProduct seckillProduct = seckillProductService.getById(productId);
                if (Objects.nonNull(seckillProduct)) {
                    SeckillActivity seckillActivity = seckillActivityService.getById(seckillProduct.getActivityId());
                    List<EbNoParticipationEntity> ebNoParticipationEntities = ebNoParticipationMapper.selectAll();
                    String string = ebNoParticipationEntities.stream().map(EbNoParticipationEntity::getName).collect(Collectors.joining(","));
                    String[] strings = StrUtil.splitToArray(string, ",");
                    if (StrUtil.equalsAnyIgnoreCase(seckillActivity.getName(), strings)) {
                        return;
                    }
                }
            }
        }
        // 普通商品
        List<OrderDetail> orderProductOrdinary = orderDetailList.stream().parallel()
                .filter(orderDetail -> orderDetail.getProductMarketingType() == 0).toList();

        long userCountOrder = orderService.count(Wrappers.<Order>lambdaQuery().eq(Order::getUid, orderInfo.getUid()));
        long pentUserCountOrder = orderService.count(Wrappers.<Order>lambdaQuery().eq(Order::getUid, orderInfo.getPUid()));
        List<Product> products = productService.findByIds(orderDetailInfo.stream().map(OrderDetail::getProductId)
                .collect(Collectors.toList()));

        EbUserRelationshipEntity userTree = userRelationshipService.getOne(userRelationshipService.from().where(EbUserRelationshipEntity::getUid).eq(orderInfo.getUid()));
        // TODO 团队(预留后期实现)
        List<EbUserRelationshipEntity> teamTree = Objects.nonNull(userTree) && userTree.getTeam() > 0 ?
                userRelationshipService.list(userRelationshipService.from().where(EbUserRelationshipEntity::getTeam).eq(userTree.getTeam()))
                : new ArrayList<>();
        // 用户原余额
        EbUserBalanceRecordEntity ebUserBalanceRecordEntity = balanceRecordMapper.selectOneByQuery(QueryWrapper.create().from(EbUserBalanceRecordEntity.class)
                .where(EbUserBalanceRecordEntity::getUid).eq(orderInfo.getUid()).orderBy(EbUserBalanceRecordEntity::getCreateTime).desc().limit(1));
        // 绑定关系
        if (Objects.isNull(orderInfo.getPUid())) {
            EbUserRelationshipEntity relationshipEntity = userRelationshipService.getOne(userRelationshipService.from().where(EbUserRelationshipEntity::getUid)
                    .eq(orderInfo.getUid()).eq(EbUserRelationshipEntity::getPId, orderInfo.getPUid())
                    .eq(EbUserRelationshipEntity::getIsEstablish, 1));
            if (Objects.isNull(relationshipEntity)) {
                EbUserRelationshipEntity relationship = userRelationshipService.getOne(userRelationshipService.from()
                        .where(EbUserRelationshipEntity::getUid).eq(orderInfo.getUid())
                        .eq(EbUserRelationshipEntity::getPId, 0)
                        .eq(EbUserRelationshipEntity::getIsEstablish, 1));
                if (Objects.isNull(relationship)) {
                    userRelationshipService.save(EbUserRelationshipEntity.builder().uid(Long.valueOf(orderInfo.getUid()))
                            .isFirstOrder(0).pId(0L).isEstablish(1).createTime(LocalDateTime.now()).build());
                }
            }
        }

        // 前后三级一共三级
        EbUserRelationshipEntity one = userRelationshipService.getOne(QueryWrapper.create()
                .from(EbUserRelationshipEntity.class).where(EbUserRelationshipEntity::getUid).eq(orderInfo.getUid()));
        BigDecimal balance = Objects.isNull(ebUserBalanceRecordEntity) ? BigDecimal.ZERO : ebUserBalanceRecordEntity.getBalance();
        List<EbUserBalanceRecordEntity> userBalanceRecordDatas = new CopyOnWriteArrayList<>();
        // 积分记录
        integralProductRecordService.saveBatch(handlerOrderData(orderId, (product, orderDetails, order, uid, isSeckill) -> {
            Integer num = Objects.isNull(product.getSeckillId()) ? orderDetails.get(String.valueOf(product.getId())) : orderDetails.get(String.valueOf(product.getSeckillId()));
            BigDecimal integral = isSeckill ? product.getPoints()
                    .multiply(BigDecimal.valueOf(num))
                    .setScale(2, RoundingMode.DOWN) : product.getPoints()
                    .multiply(BigDecimal.valueOf(num));
            String mark = String.format("用户订单付款成功,获得%s积分", integral);
            return EbUserIntegralProductRecordEntity.builder().status(2).uid(Math.toIntExact(uid))
                    .integral(integral).createTime(LocalDateTime.now()).type(3).mark(mark).linkId(orderId).build();
        }));

//        if (CollUtil.isNotEmpty(userBalanceRecordDatas)) {
//            balanceRecordMapper.insertBatch(userBalanceRecordDatas);
//        }
        if (Objects.nonNull(one)) {
            // 临时关系改为永久
            if (one.getIsEstablish() == 0) {
                userRelationshipService.updateById(one.setIsEstablish(1));
            }
            EbUserRelationshipEntity two = null;
            if (Objects.nonNull(one)) {
                two = userRelationshipService.getOne(QueryWrapper.create()
                        .from(EbUserRelationshipEntity.class).where(EbUserRelationshipEntity::getUid)
                        .eq(one.getPId()).eq(EbUserRelationshipEntity::getIsEstablish, 1));
                if (Objects.nonNull(one) && Objects.isNull(two)) {
                    two = EbUserRelationshipEntity.builder().uid(Long.valueOf(one.getPId()))
                            .isFirstOrder(0).pId(0L).isEstablish(1).createTime(LocalDateTime.now()).build();
                    EbUserRelationshipEntity relationship = userRelationshipService.getOne(userRelationshipService.from()
                            .where(EbUserRelationshipEntity::getUid).eq(orderInfo.getUid())
                            .eq(EbUserRelationshipEntity::getPId, 0)
                            .eq(EbUserRelationshipEntity::getIsEstablish, 1));
                    if (Objects.isNull(relationship)) {
                        userRelationshipService.save(two);
                    }
                }
            }
            EbUserRelationshipEntity two1 = null;
            two1 = userRelationshipService.getOne(QueryWrapper.create()
                    .from(EbUserRelationshipEntity.class).where(EbUserRelationshipEntity::getUid).eq(two.getPId()));
            if (Objects.nonNull(two) && !(two.getPId().equals(0L))) {
                two1 = EbUserRelationshipEntity.builder().uid(Long.valueOf(two.getPId()))
                        .isFirstOrder(0).pId(0L).createTime(LocalDateTime.now()).build();
                EbUserRelationshipEntity relationship = userRelationshipService.getOne(userRelationshipService.from()
                        .where(EbUserRelationshipEntity::getUid).eq(orderInfo.getUid())
                        .eq(EbUserRelationshipEntity::getPId, 0)
                        .eq(EbUserRelationshipEntity::getIsEstablish, 1));
                if (Objects.isNull(relationship)) {
                    userRelationshipService.save(two1);
                }
            }

            // 上下级关系绑定
            if (Objects.nonNull(orderInfo.getPUid())) { // dev_java_mar utf8mb4_general_ci
                // 普通商品 userCountOrder > 1 &&
                if (CollUtil.isNotEmpty(orderProductOrdinary)) {
                    List<BigDecimal> objects = handlerOrderData(orderId, (product, orderDetails, order, uid, isSeckill) -> {
                        // 复购没有余额
//                    List<OrderDetail> list1 = orderDetailService.list(Wrappers.<OrderDetail>lambdaQuery().eq(OrderDetail::getUid, orderInfo.getPUid())
//                            .eq(OrderDetail::getProductId, product.getId()));
                        Integer purchaseNum = getProductNum(orderId, product.getId());
                        return
//                            !list1.isEmpty() ? BigDecimal.ZERO :
//                            return
                                product.getPoints().multiply(BigDecimal.valueOf(purchaseNum)).multiply(dividendConfig.getExpand().getProductProp()).setScale(2, RoundingMode.DOWN);
                    });

                    BigDecimal reduce = objects.parallelStream().reduce(BigDecimal.ZERO, BigDecimal::add);

                    balanceRecordMapper.insert(userFlow(orderInfo.getOrderNo(), reduce, Objects.isNull(ebUserBalanceRecordEntity) ? BigDecimal.ZERO : ebUserBalanceRecordEntity.getBalance(),
                            Long.valueOf(one.getUid()), one.getPId(), "直邀奖励"));
                }

                EbUserRelationshipEntity relationshipEntity = userRelationshipService.getOne(userRelationshipService.from()
                        .where(EbUserRelationshipEntity::getUid).eq(orderInfo.getUid())
                        .eq(EbUserRelationshipEntity::getPId, one.getPId()));
                // 关系不存在绑定
                if (Objects.isNull(relationshipEntity)) {
                    long count = orderService.count(Wrappers.<Order>lambdaQuery().eq(Order::getUid, orderInfo.getUid()));
                    // 首单(废弃字段)
                    int isFirstOrder = count > 0 ? 0 : 1;
                    userRelationshipService.save(EbUserRelationshipEntity.builder().uid(Long.valueOf(orderInfo.getUid()))
                            .isFirstOrder(isFirstOrder).pId(Long.valueOf(orderInfo.getPUid())).createTime(LocalDateTime.now()).build());
                }
            }

            // 秒杀商品(7天自动收货)
            if (!orderDetailInfo.isEmpty()) {
                long delayTime = SystemClock.now() + Duration.ofDays(7).toMillis();
                redisTemplate.opsForZSet().add(ORDER_AUTO_CONFIRM, orderId, delayTime);
            }
            // 没有订单不参与分成
            if (!orderDetailInfo.isEmpty()) {
                // 新人福利退出
                Integer productId = orderDetailInfo.getFirst().getProductId();
                if (Objects.nonNull(productId)) {
                    SeckillProduct seckillProduct = seckillProductService.getById(productId);
                    if (Objects.nonNull(seckillProduct)) {
                        SeckillActivity seckillActivity = seckillActivityService.getById(seckillProduct.getActivityId());
                        if (seckillProduct.getName().equalsIgnoreCase("新人福利")) {
                            return;
                        }
                    }
                }
                // 三级
                EbUserRelationshipEntity finalTwo = two1;
                EbUserRelationshipEntity finalTwo1 = two;
//                redisLockClient.lockReentrant("order_balance:" + orderId, 200L, 400L, () -> {
                if (Objects.nonNull(finalTwo)) {
                    // 下线均分5%
                    BigDecimal offline = integral(orderId, dividendConfig.getExpand().getThreeLevelProp());
                    List<EbUserRelationshipEntity> shareEquallyData = userRelationshipService.list(userRelationshipService.from()
                            .where(EbUserRelationshipEntity::getPId).eq(finalTwo1.getUid()));
                    BigDecimal divide = offline.divide(new BigDecimal(shareEquallyData.size()), 2, RoundingMode.DOWN);
                    userBalanceRecordDatas.addAll(shareEqually(orderId, divide, balance, Long.valueOf(orderInfo.getUid()), shareEquallyData, true));

                    // 上线1%
                    BigDecimal goOnline = integral(orderId, dividendConfig.getExpand().getOneLevelProp());
                    userBalanceRecordDatas.add(userFlow(orderInfo.getOrderNo(), goOnline, balance,
                            Long.valueOf(orderInfo.getUid()), finalTwo.getUid(), "见点奖励"));
                    userBalanceRecordDatas.add(userFlow(orderInfo.getOrderNo(), goOnline, balance,
                            Long.valueOf(orderInfo.getUid()), finalTwo.getUid(), "推荐奖励"));
                    // 中间10%
                    BigDecimal you = integral(orderId, dividendConfig.getExpand().getTwoLevelProp());
                    userBalanceRecordDatas.add(userFlow(orderInfo.getOrderNo(), you, balance,
                            Long.valueOf(orderInfo.getUid()), finalTwo1.getUid(), "直邀奖励"));
                }
                if (Objects.isNull(finalTwo1)) {
                    BigDecimal junior = integral(orderId, dividendConfig.getExpand().getThreeLevelProp());
                    userBalanceRecordDatas.add(userFlow(orderInfo.getOrderNo(), junior, balance,
                            Long.valueOf(orderInfo.getUid()), Long.valueOf(orderInfo.getUid()), ""));
                }
                // 没有三级
                if (Objects.isNull(finalTwo) || Objects.isNull(finalTwo1)) {
                    // 一级
                    if (Objects.isNull(finalTwo1)) {
                        BigDecimal you = integral(orderId, dividendConfig.getExpand().getTwoLevelProp());
                        userBalanceRecordDatas.add(userFlow(orderInfo.getOrderNo(), you, balance,
                                Long.valueOf(one.getUid()), one.getPId(), ""));
                    } else {
                        // 两级
                        BigDecimal you = integral(orderId, dividendConfig.getExpand().getTwoLevelProp());
                        userBalanceRecordDatas.add(userFlow(orderInfo.getOrderNo(), you, balance,
                                Long.valueOf(orderInfo.getUid()), one.getPId(), "直推"));
                        // 上级见点奖励
//                            BigDecimal goOnline = integral(orderId, dividendConfig.getExpand().getThreeLevelProp());
//                            userBalanceRecordDatas.add(userFlow(orderInfo.getOrderNo(), goOnline, balance,
//                                    Long.valueOf(orderInfo.getUid()), Long.valueOf(orderInfo.getUid()), "见点奖励"));
                        // 有下级没有上级
                        BigDecimal junior = integral(orderId, dividendConfig.getExpand().getThreeLevelProp());
                        List<EbUserRelationshipEntity> list1 = userRelationshipService.list(userRelationshipService.from().where(EbUserRelationshipEntity::getPId).eq(finalTwo1.getUid()));
                        BigDecimal divide = junior.divide(new BigDecimal(list1.size()), 2, RoundingMode.DOWN);
                        userBalanceRecordDatas.addAll(shareEqually(orderId, divide, balance, Long.valueOf(orderInfo.getUid()), list1, true));
                    }
                }

//                    return true;
//                });
            }
        } else if (Objects.isNull(one) && !orderDetailInfo.isEmpty()) {
            // 没有层级消费就有5%
            BigDecimal goOnline = integral(orderId, dividendConfig.getExpand().getThreeLevelProp());
            userBalanceRecordDatas.add(userFlow(orderInfo.getOrderNo(), goOnline, balance,
                    Long.valueOf(orderInfo.getUid()), Long.valueOf(orderInfo.getUid()), "见点奖励"));
        }
        if (CollUtil.isNotEmpty(userBalanceRecordDatas)) {
            balanceRecordMapper.insertBatch(userBalanceRecordDatas);
        }
    }

    /**
     * 7天自动收货
     */
    @Scheduled(fixedRate = 120000)
    public void checkAutoConfirmOrders() {
        long now = System.currentTimeMillis();
        Set<Object> expiredOrders = redisTemplate.opsForZSet().rangeByScore(ORDER_AUTO_CONFIRM, 0, now);
        log.debug("开始检查未收货订单有：{}", JSONUtil.toJsonStr(expiredOrders));
        if (Objects.nonNull(expiredOrders)) {
            expiredOrders.forEach(orderId -> {
                Order order = orderService.getByOrderNo((String) orderId);
                if (order != null && order.getStatus() == 4) {
                    frontOrderService.takeDelivery(order.getOrderNo());
                    redisTemplate.opsForZSet().remove(ORDER_AUTO_CONFIRM, orderId);
                    log.info("自动确认收货完成：{}", orderId);
                }
            });
        }
    }

    public BigDecimal integral(String orderId, BigDecimal pip) {
        AtomicReference<BigDecimal> object = new AtomicReference<>();
        redisLockClient.lockReentrant("integral_lock:" + orderId, 200L, 500L, () -> {
            List<BigDecimal> objects = handlerOrderData(orderId, (product, orderDetails, order, uid, isSeckill) -> {
                BigDecimal multiply = product.getPrice()
                        .multiply(BigDecimal.valueOf(getProductNum(orderId, product.getId())))
                        .multiply(pip);
                return multiply.setScale(2, RoundingMode.DOWN);
            });
            object.set(objects.parallelStream().reduce(BigDecimal.ZERO, BigDecimal::add));
            return true;
        });
        return object.get();
    }

    /**
     * 平分分成
     *
     * @param orderId 订单号
     * @param average 平均值
     * @param balance 余额
     * @param uid     用户id
     * @param list1   用户关系
     * @return 分成记录
     */
    public List<EbUserBalanceRecordEntity> shareEqually(String orderId, BigDecimal average, BigDecimal balance, Long uid,
                                                        List<EbUserRelationshipEntity> list1, Boolean isDividend) {
        List<EbUserBalanceRecordEntity> recordEntities = list1.stream().map(e -> userFlow(orderId, average, balance, uid, e.getUid(), "见点分成"))
                .filter(Objects::nonNull).toList();
        if (isDividend) {
            return recordEntities;
        }
        List<EbUserBalanceRecordEntity> list = new ArrayList<>();

        Map<Integer, BigDecimal> bigDecimalMap = recordEntities.stream().collect(Collectors.groupingByConcurrent(EbUserBalanceRecordEntity::getUid, summingBigDecimal(EbUserBalanceRecordEntity::getAmount)));
        for (Map.Entry<Integer, BigDecimal> integerBigDecimalEntry : bigDecimalMap.entrySet()) {
            list.add(userFlow(orderId, integerBigDecimalEntry.getValue(), balance, uid, uid, "见点分成"));
        }
        return list;
    }

    /**
     * 获取商品数量
     *
     * @param orderId   订单号
     * @param productId 商品id
     * @return 商品数量
     */
    public Integer getProductNum(String orderId, Integer productId) {
        String purchaseNumData = redis.get(ORDER_PRODUCT + orderId);
        JSONObject bean = JSONUtil.toBean(purchaseNumData, JSONObject.class);
        Integer purchaseNum = bean.getInt(String.valueOf(productId).trim());
        return Objects.isNull(purchaseNum) ? 1 : purchaseNum;
    }

    /**
     * 用户余额流水
     *
     * @param orderId 订单号
     * @param average 冻结金额
     * @param balance 余额
     * @param uid     用户id
     * @return 用户余额流水
     */
    private EbUserBalanceRecordEntity userFlow(String orderId, BigDecimal average, BigDecimal balance,
                                               Long uid, Long prentId, String remarkName) {
        User byId = userService.getById(uid);
        if (Objects.isNull(byId)) {
            return null;
        }
        // 见点
        String name = userService.getById(uid).getNickname(), remark;
        remark = StrUtil.format("推广@{}用户获得{}{}冻结余额", name, remarkName, average);
        log.warn(remark);
        return EbUserBalanceRecordEntity.builder().uid(Math.toIntExact(prentId)).linkId(orderId).linkType("order").type(3)
                .createTime(LocalDateTime.now()).amount(average).balance(balance).remark(remark).build();
    }

    /**
     * 订单信息处理拼接
     *
     * @param orderId      订单Id
     * @param orderHandler 数据处理回调
     * @param <T>          数据类型
     * @return 处理后数据
     */
    @SuppressWarnings("all")
    private <T> List<T> handlerOrderData(String orderId, OrderHandler orderHandler) {
        List<Object> data = new ArrayList<>();
        List<Product> productList = redis.lRangeAll(ORDER_PROMOTION + orderId);
        List<OrderDetail> orderDetailInfo = redis.lRangeAll(ORDER_PROMOTION_DETAIL + orderId),
                orderDetails = new ArrayList<>();
        orderDetailInfo = CollUtil.isNotEmpty(orderDetailInfo) ? orderDetailInfo : orderDetailService.getByOrderNo(orderId);
        orderDetails = orderDetailInfo.stream().parallel()
                .filter(orderDetail -> orderDetail.getProductMarketingType() == 1).toList();
        Order orderInfo = orderService.getByOrderNo(orderId);
        Map<String, Integer> products = new HashMap<>();

        orderDetailInfo.stream().forEach(orderDetail -> {
            products.put(String.valueOf(orderDetail.getProductId()), orderDetail.getPayNum());
        });
        if (CollUtil.isEmpty(productList) || CollUtil.isEmpty(orderDetailInfo)) {
            if (orderDetails.size() > 0) {
                List<Long> productIds = orderDetails.stream()
                        .peek(it -> {
                                    SeckillProduct byId = seckillProductService.getById(it.getProductId());
                                    ProductAttrValue byId1 = productAttrValueService.getById(it.getAttrValueId());
                                    if (Objects.nonNull(byId1)) {

                                    }
//                                    products.computeIfAbsent(String.valueOf(byId.getProductId()), v -> it.getPayNum());
                                }
                        )
                        .map(OrderDetail::getSliderProductId).collect(Collectors.toList());
                List<SeckillProduct> seckillProducts = seckillProductService.listByIds(productIds);

                // 秒杀商品积分独立
                List<Product> finalByIds = new ArrayList<>();
                List<OrderDetail> finalOrderDetailInfo = orderDetailInfo;
                seckillProducts.forEach(seckillProduct -> {
                    Product product = productService.getById(seckillProduct.getProductId());
                    SeckillActivity seckillActivity = seckillActivityService.getById(seckillProduct.getActivityId());
                    product.setIsSpec(seckillActivity.getName().equalsIgnoreCase("新人福利"));
                    OrderDetail orderDetail = finalOrderDetailInfo.stream().parallel()
                            .filter(it -> it.getProductId().equals(seckillProduct.getId()))
                            .findFirst().get();
                    product.setSeckillId(seckillProduct.getId());
                    ProductAttrValue attrValue = productAttrValueService.lambdaQuery()
                            .eq(ProductAttrValue::getMarketingType, ProductConstants.PRODUCT_MARKETING_TYPE_SECKILL)
                            .eq(ProductAttrValue::getProductId, seckillProduct.getId())
                            .eq(ProductAttrValue::getId, orderDetail.getAttrValueId())
                            .one();
                    if (Objects.nonNull(attrValue)) {
                        product.setPoints(attrValue.getPoints());
                        product.setRewardPoints(attrValue.getRewardPoints());
                    }
                    finalByIds.add(product);
                });
                productList.addAll(finalByIds);
            } else {
                List<Product> finalByIds = new ArrayList<>();
//                productList =
                productService.findByIds(orderDetailInfo.stream()
                        .peek(it -> {
                            Product byId = productService.getById(it.getProductId());
                            ProductAttrValue byId1 = productAttrValueService.getById(it.getAttrValueId());
                            if (Objects.nonNull(byId1) && Objects.nonNull(byId)) {
                                byId.setPoints(byId1.getProIntegral());
                                byId.setRewardPoints(byId1.getRewardPoints());
                            }
                            if (Objects.nonNull(byId)) {
                                finalByIds.add(byId);
                            }
                        })
                        .map(OrderDetail::getProductId).collect(Collectors.toList()));

                productList.addAll(finalByIds);
            }
        }
        List<Object> objects = redis.lRangeAll(ORDER_PROMOTION + orderId);
        Boolean isSeckill = redis.get(ORDER_SECKILL + orderId);
        List<OrderDetail> finalOrderDetails = orderDetails;
        // 缓存数据
        if (CollUtil.isEmpty(objects)) {
            redis.rPush(ORDER_PROMOTION + orderId, productList);
            redis.rPush(ORDER_PROMOTION_DETAIL + orderId, orderDetailInfo);
            redis.setEx(ORDER_SECKILL + orderId, finalOrderDetails.size() > 0 ? true : false, ORDER_TIMEOUT);
            redis.setEx(ORDER_PRODUCT + orderId, JSONUtil.toJsonStr(products), ORDER_TIMEOUT);
            redis.expire(ORDER_PROMOTION + orderId, ORDER_TIMEOUT);
            redis.expire(ORDER_PROMOTION_DETAIL + orderId, ORDER_TIMEOUT);
            redis.expire(ORDER_PRODUCT + orderId, ORDER_TIMEOUT);
        }
        productList.stream().map(product -> orderHandler.handlerOrderData(product, products, orderInfo, Long.valueOf(orderInfo.getUid()),
                Optional.ofNullable(isSeckill).orElse(finalOrderDetails.size() > 0 ? true : false))).map(data::add).toList();
        return (List<T>) data;
    }

    /**
     * 订单数据处理
     */
    @FunctionalInterface
    public interface OrderHandler {

        /**
         * 商品后期数据处理
         *
         * @param product   商品信息
         * @param orderInfo 订单信息
         * @param uid       用户Id
         * @param isSeckill 是否秒杀订单
         */
        Object handlerOrderData(Product product, Map<String, Integer> orderDetails, Order orderInfo, Long uid, Boolean isSeckill);
    }

    @FunctionalInterface
    public interface ToBigDecimalFunction<T> {
        BigDecimal applyAsBigDecimal(T value);
    }

    public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(ToBigDecimalFunction<? super T> mapper) {
        return new SimpleCollector<>(
                () -> new BigDecimal[1],
                (a, t) -> {
                    if (a[0] == null) {
                        a[0] = BigDecimal.ZERO;
                    }
                    a[0] = a[0].add(mapper.applyAsBigDecimal(t));
                },
                (a, b) -> {
                    a[0] = a[0].add(b[0]);
                    return a;
                },
                a -> a[0],
                Collections.emptySet()
        );
    }

}
